// package  共识
package consensus

import (
	"osiris/dto"
	"osiris/logger"
	"osiris/mpt"
	"osiris/ocrypto/ecdsa"
)

// TxTrie 交易树
type TxTrie struct {
	trie *mpt.Trie
}

// Build 根据dto.TxData列表构建交易树
//
//	@receiver txTrie
//	@param txs dto.TxData列表
//	@return error
func (txTrie *TxTrie) Build(txs []dto.TxData) error {
	var errOutside error
	txTrie.trie = mpt.NewTrie()

	for _, tx := range txs {
		txHashkey := ecdsa.StrToKeccak256Hash(tx.TxHash)

		txBytes, err := dto.ToBytes(tx)
		if err != nil {
			errOutside = err
			logger.Error(map[string]interface{}{"[consensus] [TxTrie.Build()] txData to bytes": err})
			continue
		}

		txTrie.trie.Put(txHashkey[:], txBytes)
	}

	return errOutside
}

// Prove 提供某个交易hash对应的merkle proof
//
//	@receiver txTrie
//	@param txHashStr 交易hash字符串
//	@return mpt.Proof merkle proof
//	@return bool 是否存在该hash对应的交易
func (txTrie *TxTrie) Prove(txHashStr string) (mpt.Proof, bool) {
	txHashkey := ecdsa.StrToKeccak256Hash(txHashStr)
	return txTrie.trie.Prove(txHashkey[:])
}

// VerifyProof 验证merkle proof
//
//	@receiver txTrie
//	@param txHashStr 交易hash字符串
//	@param proof merkle proof
//	@return []byte 该hash对应的value（txData的字节数组）
//	@return error
func (txTrie *TxTrie) VerifyProof(txHashStr string, proof mpt.Proof) ([]byte, error) {
	txHashkey := ecdsa.StrToKeccak256Hash(txHashStr)
	return mpt.VerifyProof(txTrie.trie.Hash(), txHashkey[:], proof)
}
